package com.ruben.config;

import java.time.LocalDate;
import java.time.LocalDateTime;

import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;

import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.serializer.SerializeConfig;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;

import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.lang.Opt;

/**
 * FastJson配置
 *
 * @author <achao1441470436@gmail.com>
 * @since 2021/10/9 12:42
 */
@EnableConfigurationProperties(FastJsonProperties.class)
public class FastJsonAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean
    public FastJsonConfig fastJsonConfig(FastJsonProperties fastJsonProperties) {
        FastJsonConfig fastJsonConfig = new FastJsonConfig();
        // 配置序列化策略
        // ID_WORKER 生成主键太长导致 js 精度丢失
        // JavaScript 无法处理 Java 的长整型 Long 导致精度丢失，具体表现为主键最后两位永远为 0，解决思路： Long 转为 String 返回
        fastJsonConfig.setSerializerFeatures(SerializerFeature.BrowserCompatible,
                // 处理序列化后出现$ref的坑
                SerializerFeature.DisableCircularReferenceDetect,
                // 列化枚举值为数据库存储值
                SerializerFeature.WriteEnumUsingToString);
        SerializeConfig serializeConfig = SerializeConfig.globalInstance;
        // 设置全局LocalDateTime转换
        fastJsonConfig.setDateFormat(fastJsonProperties.getDatePattern());
        serializeConfig.put(LocalDateTime.class, (serializer, object, fieldName, fieldType, features) ->
                Opt.ofNullable(object).ifPresentOrElse(obj ->
                                serializer.out.writeString(
                                        LocalDateTimeUtil.format((LocalDateTime) obj, fastJsonProperties.getLocalDateTimePattern())
                                ),
                        serializer.out::writeNull));
        serializeConfig.put(LocalDate.class, (serializer, object, fieldName, fieldType, features) ->
                Opt.ofNullable(object).ifPresentOrElse(obj -> serializer.out.writeString(
                                LocalDateTimeUtil.format((LocalDate) obj, fastJsonProperties.getLocalDatePattern())
                        ),
                        serializer.out::writeNull));
        fastJsonConfig.setSerializeConfig(serializeConfig);
        ParserConfig parserConfig = ParserConfig.getGlobalInstance();
        fastJsonConfig.setParserConfig(parserConfig);
        return fastJsonConfig;
    }


}
